﻿using System.Linq;
using Medianamik.Core.CodeGeneration;

namespace Medianamik.Core.Action
{
    public class UpdateGenTableActionHandler : IActionHandler
    {
        public void Initialize(ActionManager events)
        {
            events.AfterCreateNodeInstance += HandleCreateNodeInstance;
            events.AfterUpdateNodeInstance += HandleUpdateNodeInstance;
            events.AfterPublishNodeInstance += HandlePublish;
            events.BeforeDeleteNodeInstance += HandleDeleteInstance;
            events.BeforeDeleteNode += HandleDeleteNode;
            events.AfterRevertNodeInstance += HandleRevert;
            events.AfterChangeNodeInstanceActiveStatus += AfterChangeNodeInstanceActiveStatus;
            events.AfterMoveNode += AfterMoveNode;
        }

        //Il faut updater l'ensemble des instances, en draft et published
        void AfterMoveNode(NodeMovedEventArgs args)
        {
            if (args.Item.NodeType.IsGenerated)
            {
                var codeService = new CodeService();
                args.Item.Instances.ForEach(i=> Publish(i, codeService, true));
            }
        }

        public string Description
        {
            get { return "Met à jour les tables générées"; }
        }

        void AfterChangeNodeInstanceActiveStatus(ActionEventArgs<NodeInstance> args)
        {
            if (args.Item.Node.NodeType.IsGenerated)
            {
                var code = new CodeService();
                code.DeleteDraftAndPublished(args.Item);
                code.InsertAllRecords(args.Item);
            }
        }

        void HandleRevert(ActionEventArgs<NodeInstance> obj)
        {
            if (obj.Item.Node.NodeType.IsGenerated
                && obj.Item.Properties.Any(p => p.IsOwnProperty && p.Revision.HasValue))
            {
                var codeService = new CodeService();
                codeService.DeleteDraftRecord(obj.Item);
                codeService.InsertDraftRecord(obj.Item);
            }
        }

        private void HandleCreateNodeInstance(ActionEventArgs<NodeInstance> args)
        {
            if (args.Item.Node.NodeType.IsGenerated
                && args.Item.Properties.Any(p => p.IsOwnProperty && !p.Revision.HasValue))
            {
                new CodeService().InsertRecord(args.Item, false);
            }
        }

        private void HandleUpdateNodeInstance(ActionEventArgs<NodeInstance> args)
        {
            if (args.Item.Node.NodeType.IsGenerated)
            {
                new CodeService().UpdateRecord(args.Item);
            }
        }

        private void HandleDeleteInstance(ActionEventArgs<NodeInstance> args)
        {
            if (args.Item.Node.NodeType.IsGenerated)
            {
                new CodeService().DeleteDraftAndPublished(args.Item);
            }
        }

        private void HandleDeleteNode(ActionEventArgs<Node> args)
        {
            if (args.Item.NodeType.IsGenerated)
            {
                //Effacer toutes les instances d'un noeud
                var codeService = new CodeService();

                args.Item.Instances.ForEach(codeService.DeleteDraftAndPublished);
            }
        }

        private void HandlePublish(ActionEventArgs<NodeInstance> args)
        {
            if (args.Item.Node.NodeType.IsGenerated)
            {
                var codeService = new CodeService();
                Publish(args.Item, codeService, false);
            }
        }

        private void Publish(NodeInstance nodeInstance, CodeService codeService, bool moved)
        {
            //Delete parce qu'on ne peut-être certain qu'il y a deja une version publiée et pas de merge (SQL2008 seulement)
            if (nodeInstance.Node.NodeType.IsVersioned)
            {
                codeService.DeletePublishedRecord(nodeInstance);
                codeService.InsertRecord(nodeInstance, true); //Published
            }

            if(moved)
                codeService.UpdateRecord(nodeInstance); //Draft
        }
    }
}